package com.atguigu.tingshu.common.aspect;

import com.alibaba.fastjson.JSON;
import com.atguigu.tingshu.common.anno.GuiGuLogin;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.user.UserInfo;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

@Component
@Aspect
@Slf4j
public class GuiGuLoginAspect {


    @Autowired
    private RedisTemplate<String ,String > redisTemplate;
    
    @Around("@annotation(guiGuLogin)")
    public  Object around(ProceedingJoinPoint proceedingJoinPoint ,GuiGuLogin guiGuLogin){

        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        String token = request.getHeader("token");
        boolean required = guiGuLogin.required();

        //  判断是否需要登录
        if (required){

            //  必须要登录，token 为空是抛出异常
            if (StringUtils.isEmpty(token)){
                throw new GuiguException(ResultCodeEnum.LOGIN_AUTH);   //  没有token 要抛出异常
            }

            //  如果token 不为空，从缓存中获取信息.
            String userInfoJSON =  this.redisTemplate.opsForValue().get(RedisConstant.USER_LOGIN_KEY_PREFIX + token);

            //  判断对象是否为空
            if (StringUtils.isEmpty(userInfoJSON)){
                throw new GuiguException(ResultCodeEnum.LOGIN_AUTH);            //  抛出异常信息
            }

            // 将用户信息存储到ThreadLocal中
            UserInfo userInfo = JSON.parseObject(userInfoJSON, UserInfo.class);
            AuthContextHolder.setUserId(userInfo.getId());
            AuthContextHolder.setUsername(userInfo.getNickname());

        }else {

            //  不需要强制登录,但是，有可能需用到用户信息.
            if (!StringUtils.isEmpty(token)){

                //  如果token 不为空，从缓存中获取信息.
                String userInfoJSON =  this.redisTemplate.opsForValue().get(RedisConstant.USER_LOGIN_KEY_PREFIX + token);
                if (!StringUtils.isEmpty(userInfoJSON)){

                    //  将用户信息存储到ThreadLocal中
                    UserInfo userInfo = JSON.parseObject(userInfoJSON, UserInfo.class);
                    AuthContextHolder.setUserId(userInfo.getId());
                    AuthContextHolder.setUsername(userInfo.getNickname());

                }

            }

        }


        try {

            // 执行目标方法
            Object proceed = proceedingJoinPoint.proceed();

            // 返回
            return proceed ;

        }catch (Throwable e) {
            e.printStackTrace();
            if(e instanceof GuiguException){
                throw (GuiguException)e;
            }else {
                throw  new RuntimeException(e);
            }
        } finally {

            // 从ThreadLocal中删除数据，防止内存泄漏
            AuthContextHolder.removeUserId();
            AuthContextHolder.removeUsername();
        }


    }
}